#include "TdSpi.h"
#include <iostream>
#include <string.h>
#include "Timer.hpp"
using namespace std;
extern pthread_cond_t doneCond; 
extern pthread_mutex_t doneMutex; 
TdSpi::TdSpi()
{
}

bool IsErrorRspInfo(CThostFtdcRspInfoField *pRspInfo)
{
    bool bResult = ((pRspInfo) && (pRspInfo->ErrorID != 0));
    if (bResult)
    {
        cerr << ">>> ErrorID=" << pRspInfo->ErrorID<<endl;// << ", ErrorMsg=" << pRspInfo->ErrorMsg << endl;
    }
    return bResult;
}

void TdSpi:: OnFrontDisconnected(int nReason)
{
    cerr << ">>> MdFrontDisconnected Reason = " << nReason << endl;
}

void TdSpi::OnHeartBeatWarning(int nTimeLapse)
{
    cerr << ">>> TradeHeartBeatWarning nTimerLapse = " << nTimeLapse << endl;
}

void TdSpi::OnFrontConnected()
{
    pthread_mutex_lock(&doneMutex);     
    pthread_cond_signal(&doneCond); 
    pthread_mutex_unlock (&doneMutex); 
}

void TdSpi::OnRspAuthenticate(CThostFtdcRspAuthenticateField *pRspAuthenticateField,CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex);
        pthread_cond_signal(&doneCond);
        pthread_mutex_unlock (&doneMutex);
    }

}

void TdSpi::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin,
                               CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex); 
        pthread_cond_signal(&doneCond); 
        pthread_mutex_unlock (&doneMutex); 

    }
}


void TdSpi::OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField *pSettlementInfoConfirm, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    pthread_mutex_lock(&doneMutex); 
    pthread_cond_signal(&doneCond); 
    pthread_mutex_unlock (&doneMutex); 

}

void TdSpi::OnRspOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    fprintf(stderr,"id: %s %s ErrorID:%d\n", pInputOrder->OrderRef,  pInputOrder->InstrumentID, pRspInfo->ErrorID);
}

void TdSpi::OnRspOrderAction(CThostFtdcInputOrderActionField *Rtn, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{

    cerr << ">>> OnRspOrderAction"<< endl;
    IsErrorRspInfo(pRspInfo);
}


void TdSpi::OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    cerr << ">>> OnRspError"<< endl;
    IsErrorRspInfo(pRspInfo);
}

void TdSpi::OnRtnOrder(CThostFtdcOrderField *Rtn)
{
    if(!Rtn)
		return;
	if(Rtn->OrderStatus==THOST_FTDC_OST_Unknown)
		return;
	if(strcmp(Rtn->InstrumentID, target.symbol)!=0)
		return;
	if(target.rtn_order_nano==0)
		target.rtn_order_nano = Timer::getNano();
	target.entrust_volume = Rtn->VolumeTotal;
//	fprintf(stderr,"id:%s %s %s %s%s %d %d status:%c\n",Rtn->OrderRef,Timer::nano2str(target.rtn_order_nano).c_str(), Rtn->InstrumentID, (Rtn->Direction==THOST_FTDC_D_Buy?"Buy":"Sell"),(Rtn->CombOffsetFlag[0]==THOST_FTDC_OF_Open?"Open ":"Close"), Rtn->VolumeTotal, Rtn->VolumeTraded, Rtn->OrderStatus);
	if( Rtn->OrderStatus == THOST_FTDC_OST_AllTraded )
	{
		int volume = Rtn->VolumeTraded * (Rtn->Direction==THOST_FTDC_D_Buy?1:-1);
		if(Rtn->CombOffsetFlag[0]==THOST_FTDC_OF_Close)
		{
			yesterday_position[Rtn->InstrumentID] += volume;
		}
		else
		{
			today_position[Rtn->InstrumentID] += volume;
		}

	}
}

void TdSpi::OnRtnTrade(CThostFtdcTradeField *Rtn)
{
	if(target.first_trade_nano==0)
		target.first_trade_nano = Timer::getNano();
	target.last_trade_nano = Timer::getNano();
	target.deal_price = Rtn->Price;
	target.deal_volume += Rtn->Volume;
//	fprintf(stderr,"\t%s %c %c %d@%.0f\n", Rtn->InstrumentID, (Rtn->Direction==THOST_FTDC_D_Buy?'B':'S'),Rtn->OffsetFlag, Rtn->Volume, Rtn->Price);
	if(target.deal_volume == target.target_volume)
	{
        pthread_mutex_lock(&doneMutex); 
        pthread_cond_signal(&doneCond); 
        pthread_mutex_unlock (&doneMutex); 
	}
}


void TdSpi::OnRspQryInvestorPositionDetail(CThostFtdcInvestorPositionDetailField *Rtn, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    if(Rtn)
	{
		if(Rtn->Volume!=0)
		{
			string symbol = Rtn->InstrumentID;
			int volume = Rtn->Volume * (Rtn->Direction==THOST_FTDC_D_Buy?1:-1);
			bool istoday = strcmp(Rtn->OpenDate, Rtn->TradingDay)==0;
			fprintf(stderr,"%10s %s %d@%f\n",istoday?"today":"yesterday",Rtn->InstrumentID, volume, Rtn->OpenPrice);
			if(istoday)
				today_position[symbol] += volume;
			else
				yesterday_position[symbol] += volume;
		}
	}
    if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex); 
        pthread_cond_signal(&doneCond); 
        pthread_mutex_unlock (&doneMutex); 
    }
}

void TdSpi::OnRtnInstrumentStatus(CThostFtdcInstrumentStatusField *Rtn)
{
	if(Timer::isClose( Timer::time2int(Rtn->EnterTime, 0 ) ) )
		market_close = true;
}

bool TdSpi::isClosed()
{
	return market_close;
}
const Order* TdSpi::getTarget()
{
	return &target;
}

void TdSpi::setTarget(const Order* order)
{
	memcpy(&target, order, sizeof(Order));
	target.sent_nano = Timer::getNano();
//	fprintf(stderr,"id:%d %3.0fus %3.0fus %3.0fus %s %c %c %d@%.3f\n",target.id,(target.process_nano - target.md_nano)*1e-3, (target.order_nano - target.process_nano)*1e-3, (target.sent_nano - target.order_nano )*1e-3,target.symbol, target.direction, target.offset,target.target_volume, target.order_price);
}

char TdSpi::checkPosition(string symbol)
{
	if(yesterday_position.find(symbol) != yesterday_position.end())
	{
		if(yesterday_position[symbol] != 0)
			return THOST_FTDC_OF_Close;
	}
	return THOST_FTDC_OF_CloseToday;
}

